#!/usr/bin/env python
# encoding: utf-8
from pyo import *
from dictionnaire import *

class AudioServer:
    def __init__(self):
        self.project = []
        self.server = Server()
        self.server.boot()
        
    def serverStart(self):
        self.server.start()
        
    def serverStop(self):
        self.server.stop()
        
    def controlVolume(self, gain):
        self.server.setAmp(gain)
        
    def getProject(self):
        return self.project
        
    def addModule(self, name):
        self.project.append(name)
        
        
class InstGenerator:
    def __init__(self, dictionary, list, tempo, index, amp, dec, lfoFreq, lfoMul):
        self.dict = dictionary
        self.list = list
        self.tempo = tempo
        self.lfoFreq = SigTo(lfoFreq, init=lfoFreq)
        self.lfoMul = SigTo(lfoMul, init=lfoMul)
        
        self.generalVolume = SigTo(amp, init=amp)
        self.generalDecay = SigTo(dec, init=dec)
        
        self.indexLfo = Sine(self.lfoFreq, mul=self.lfoMul, add=self.lfoMul).play()
        self.index = SigTo(index, init=index, mul=1+self.indexLfo)
        
        self.durTable = LinTable(list=self.dict["durations"], size=8192)
        self.durDec = TableIndex(self.durTable, self.index, mul=1)
        
        
        self.sixAtt = LinTable(list=self.dict["a6"], size=8192)
        self.sevenAtt = LinTable(list=self.dict["a7"], size=8192)
        self.eightAtt = LinTable(list=self.dict["a8"], size=8192)
        self.nineAtt = LinTable(list=self.dict["a9"], size=8192)
        self.volumeAtt = LinTable(list=self.dict["volAtt"], size=8192)
        self.masterAtt = NewTable(8192./44100, chnls=4, init=None, feedback=0.00)
        self.morphingAtt= TableMorph(self.index, table=self.masterAtt, sources=[self.sixAtt, self.sevenAtt, self.eightAtt, self.nineAtt])
        self.freqsAtt = LinTable(list=self.dict["freqAtt"], size=8192)
        self.currentAttFreq = TableIndex(self.freqsAtt, self.index, mul=10000)
        self.currentAttVol = TableIndex(self.volumeAtt, self.index)

 
        
        self.sixDec = CosTable(list=self.dict["d6"], size=8192)
        self.sevenDec = CosTable(list=self.dict["d7"], size=8192)
        self.eightDec = CosTable(list=self.dict["d8"], size=8192)
        self.nineDec = CosTable(list=self.dict["d9"], size=8192)
        self.volumeDec = LinTable(list=self.dict["volDec"], size=8192)
        self.masterDec = NewTable(8192./44100, chnls=1, init=None, feedback=0.00)
        self.morphingDec= TableMorph(self.index, table=self.masterDec, sources=[self.sixDec, self.sevenDec, self.eightDec, self.nineDec])
        self.freqsDec = LinTable(list=self.dict["freqDec"], size=8192)
        self.currentDecFreq = TableIndex(self.freqsDec, self.index, mul=10000)
        self.currentDecVol = TableIndex(self.volumeDec, self.index)

        
        
        self.sixDec2 = CosTable(list=self.dict["d26"], size=8192)
        self.sevenDec2 = CosTable(list=self.dict["d27"], size=8192)
        self.eightDec2 = CosTable(list=self.dict["d28"], size=8192)
        self.nineDec2 = CosTable(list=self.dict["d29"], size=8192)
        self.volumeDec2 = LinTable(list=self.dict["volDec2"], size=8192)
        self.masterDec2 = NewTable(8192./44100, chnls=1, init=None, feedback=0.00)
        self.morphingDec2= TableMorph(self.index, table=self.masterDec2, sources=[self.sixDec2, self.sevenDec2, self.eightDec2, self.nineDec2])
        self.freqsDec2 = LinTable(list=self.dict["freqDec2"], size=8192)        
        self.currentDec2Freq = TableIndex(self.freqsDec2, self.index, mul=10000)
        self.currentDec2Vol = TableIndex(self.volumeDec2, self.index)


        
        self.sixDec3 = CosTable(list=self.dict["d36"], size=8192)
        self.sevenDec3 = CosTable(list=self.dict["d37"], size=8192)
        self.eightDec3 = CosTable(list=self.dict["d38"], size=8192)
        self.nineDec3 = CosTable(list=self.dict["d39"], size=8192)
        self.volumeDec3 = LinTable(list=self.dict["volDec3"], size=8192)
        self.masterDec3 = NewTable(8192./44100, chnls=1, init=None, feedback=0.00)
        self.morphingDec3= TableMorph(self.index, table=self.masterDec3, sources=[self.sixDec3, self.sevenDec3, self.eightDec3, self.nineDec3])
        self.freqsDec3 = LinTable(list=self.dict["freqDec3"], size=8192)
        self.currentDec3Freq = TableIndex(self.freqsDec3, self.index, mul=10000)
        self.currentDec3Vol = TableIndex(self.volumeDec3, self.index)
                                
        self.tap = Iter(self.tempo.mix(1), choice=self.list)

        # On se sert du tap pour laisser passer (ou non) le trig du metro
        self.trig = self.tempo * self.tap

        self.trigEn1 = TrigEnv(self.trig, self.masterAtt, dur=self.durDec*self.generalDecay, interp=2, mul=self.currentAttVol)
        self.trigEn2 = TrigEnv(self.trig, self.masterDec, dur=self.durDec*self.generalDecay, interp=2, mul=self.currentDecVol)
        self.trigEn3 = TrigEnv(self.trig, self.masterDec2, dur=self.durDec*self.generalDecay, interp=2, mul=self.currentDec2Vol)
        self.trigEn4 = TrigEnv(self.trig, self.masterDec3, dur=self.durDec*self.generalDecay, interp=2, mul=self.currentDec3Vol)
       
       
        self.n = Noise()
        self.a = Biquadx(self.n, freq=self.currentAttFreq, q=1, type=self.dict["filterType"], stages=4, mul=self.trigEn1)

        self.tblDec = HarmTable(list=self.dict["waveHarmonics"], size=8192)
        self.d = OscTrig(self.tblDec, self.trig, freq=self.currentDecFreq, phase=0, interp=2, mul=self.trigEn2)

        self.d2 = OscTrig(self.tblDec, self.trig, freq=self.currentDec2Freq, phase=0, interp=2, mul=self.trigEn3)

        self.d3 = OscTrig(self.tblDec, self.trig, freq=self.currentDec3Freq, phase=0, interp=2, mul=self.trigEn4)

        self.filter = Biquadx(self.a + self.d, freq=49, q=1, type=1, stages=4, mul=self.generalVolume).mix(1).mix(2).out()
        
    def out(self):
        return self.filter.mix(1).mix(2).out()
        
    def getStates(self):
        states = {}
        states.append(self.index)
        states.append(self.list)
        return states
        
    def changeAmp(self, newVol):
        self.generalVolume.setValue(newVol)

    def changeDec(self, newDecay):
        self.generalDecay.setValue(newDecay)

    def changeLfoFreq(self, newFreq):
        self.lfoFreq.setValue(newFreq)
        if newFreq == 0:
            self.indexLfo.stop()
        else:
            self.indexLfo.play()
        
    def changeLfoMul(self, newMul):
        self.lfoMul.setValue(newMul)
        if newMul == 0:
            self.indexLfo.stop()
        else:
            self.indexLfo.play()
        
    def morphTables(self, newIndex):
        self.index.setValue(newIndex)
        
    def editMeasure(self, newMeasure):
        self.list = newMeasure
        self.tap.setChoice(newMeasure)
